package com.zijidelu.luframework.infrastructure.persistence.repository.core;

import com.zijidelu.luframework.base.model.DataModel;
import com.zijidelu.luframework.base.model.PO;
import com.zijidelu.luframework.infrastructure.model.api.PageQuery;
import com.zijidelu.luframework.infrastructure.model.api.PageResponse;
import com.zijidelu.luframework.infrastructure.persistence.repository.core.base.AbstractRepository;
import com.zijidelu.luframework.infrastructure.persistence.repository.core.bizsig.BizSigRepository;
import com.zijidelu.luframework.infrastructure.persistence.repository.core.data.DataRepository;
import com.zijidelu.luframework.infrastructure.persistence.repository.core.domain.calculator.DomainKeyCalculator;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 统一仓储抽象基类，集成多层核心能力的基础实现
 *
 * <p>该类作为统一仓储架构的核心抽象，通过模板方法模式整合了以下能力：
 * <ul>
 *   <li><b>业务签名管理</b> - 集成 {@link BizSigRepository} 的签名验证</li>
 *   <li><b>数据加工处理</b> - 基于 {@link DataRepository} 的数据转换逻辑</li>
 *   <li><b>领域键计算</b> - 整合 {@link DomainKeyCalculator} 的领域标识生成</li>
 * </ul>
 *
 * <p><b>设计理念：</b>通过统一的抽象基类，为具体业务仓储提供一站式的数据访问解决方案，
 * 简化多层能力的集成复杂度，确保架构一致性。
 *
 * @author ZIJIDELU
 * @date: 2024/3/6 12:20
 */
@Slf4j
public abstract class AbstractUnifiedRepository<
        P extends PO,
        D extends DataModel
        > extends AbstractRepository<P, D>
        implements UnifiedRepository<P, D> {

    /**
     * DTO数据仓库接口Provider。
     */
    @Setter(onMethod_ = @Autowired)
    private ObjectProvider<DataRepository<P, D>> dataRepositoryProvider;
    private DataRepository<P, D> dataRepository;

    /**
     * 唯一键DTO数据仓库接口Provider。
     */
    @Setter(onMethod_ = @Autowired)
    private ObjectProvider<BizSigRepository<P, D>> bizSigRepositoryProvider;
    private BizSigRepository<P, D> bizSigRepository;

    /**
     * 领域键计算接口Provider。
     */
    @Setter(onMethod_ = @Autowired)
    private ObjectProvider<DomainKeyCalculator> domainKeyCalculatorProvider;
    private DomainKeyCalculator domainKeyCalculator;

    /**
     * 获取DTO数据仓库接口。
     *
     * @return DTO数据仓库接口
     */
    public DataRepository<P, D> getDataRepository() {
        if (dataRepository == null) {
            dataRepository = dataRepositoryProvider.getIfAvailable();
        }
        return dataRepository;
    }

    /**
     * 获取唯一键DTO数据仓库接口。
     *
     * @return 唯一键DTO数据仓库接口
     */
    public BizSigRepository<P, D> getBizSigRepository() {
        if (bizSigRepository == null) {
            bizSigRepository = bizSigRepositoryProvider.getIfAvailable();
        }
        return bizSigRepository;
    }

    /**
     * 获取领域数据仓库接口。
     *
     * @return 领域数据仓库接口
     */
    public DomainKeyCalculator getDomainKeyCalculator() {
        if (domainKeyCalculator == null) {
            domainKeyCalculator = domainKeyCalculatorProvider.getIfAvailable();
        }
        return domainKeyCalculator;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public PageResponse<D> listPage(final PageQuery<D> pageQuery) {
        return PageResponse.of(getDataConverter().poToDataPage(buildGenericQueryWrapper(pageQuery.getData())
                .page(pageQuery.toPage())
        ));
    }
}
